package model

import (
	RR "crypto/rand"
	"gowork/tuokeActivity/utils"
	"math"
	"math/big"
	"math/rand"
	"sync"
	"time"
)

type Activity struct {
	Id int64 `xorm:"pk autoincr"`
	Name string
	Number int
	PurchaseCap int
	MinRandomRedPacket int64
	MaxRandomRedPacket int64
	ActivityDuration int
	ActivityStartTime time.Time
	ActivityEndTime time.Time
	State int
	CommodityList []*Commodity `xorm:"-"`
	StoreList []*Store `xorm:"-"`
	CreatedAt time.Time
	UpdatedAt time.Time
}

type ActivityParticipationRecords struct {
	Id int64 `xorm:"pk autoincr"`
	UserId int64
	ActivityId int64
	CreatedAt time.Time
	UpdatedAt time.Time
}

type UserActivity struct {
	Id int64 `xorm:"pk autoincr"`
	UserId int64
	ActivityId int64
	CreatedAt time.Time
	UpdatedAt time.Time
}

type ActivityStore struct {
	Id int64 `xorm:"pk autoincr"`
	ActivityId int64
	StoreId int64
	CreatedAt time.Time
	UpdatedAt time.Time
}

type Store struct {
	Id int64 `xorm:"pk autoincr"`
	Name string
	Participation bool `xorm:"-"`
	CreatedAt time.Time
	UpdatedAt time.Time
}

type EventPurchaseRecord struct {
	Id int64 `xorm:"pk autoincr"`
	ActivityId int64
	CreatedAt time.Time
	UpdatedAt time.Time
}

type Commodity struct {
	Id int64 `xorm:"pk autoincr"`
	Name string
	ActivityId int64
	CreatedAt time.Time
	UpdatedAt time.Time
}

type User struct {
	Id int64 `xorm:"pk autoincr"`
	Name string
	Wallet float64
	CreatedAt time.Time
	UpdatedAt time.Time
}

type UserCommodity struct {
	Id int64 `xorm:"pk autoincr"`
	UserId int64
	CommodityId int64
	CreatedAt time.Time
	UpdatedAt time.Time
}

type ShareRecords struct {
	Id int64 `xorm:"pk autoincr"`
	SharerId int64
	SharerName string
	SharedById int64
	SharedByName string
	ActivityId int64
	ActivityName string
	CreatedAt time.Time
	UpdatedAt time.Time
}

type WalletRecords struct {
	Id int64 `xorm:"pk autoincr"`
	GetRedPacketUserId int64
	RedPacketAmount float64
	CreatedAt time.Time
	UpdatedAt time.Time
}

type MedalManagement struct {
	Id int64 `xorm:"pk autoincr"`
	Name string
	MarketPrice float64
	ActivityId int64
	ExchangeRecommendation int
	MaximumExchangeTimes int
	ConvertibleAmount int
	CreatedAt time.Time
	UpdatedAt time.Time
}

type ExchangeRecords struct {
	Id int64 `xorm:"pk autoincr"`
	UserId int64
	MedalManagementId int64
	MedalManagementName string
	CreatedAt time.Time
	UpdatedAt time.Time
}

func RangeRand(min, max int64) int64 {
	if min > max {
		panic("the min is greater than max!")
	}

	if min < 0 {
		f64Min := math.Abs(float64(min))
		i64Min := int64(f64Min)
		result, _ := RR.Int(RR.Reader, big.NewInt(max+1+i64Min))

		return result.Int64() - i64Min
	} else {
		result, _ := RR.Int(RR.Reader, big.NewInt(max-min+1))
		return min + result.Int64()
	}
}

func (activity *Activity)SharedOrders(sr *ShareRecords)(map[string]interface{}, error){

	w := new(utils.Worker)

	var av Activity
	x.SQL("select * from activity where id = ? and activity_start_time <= ? and activity_end_time >= ? and state = ?", sr.ActivityId, time.Now().Format("2006-01-02 15:04:05"), time.Now().Format("2006-01-02 15:04:05"), 1).
		Get(&av)
	//x.Where("id = ?", sr.ActivityId).And("activity_start_time <= ?", time.Now()).And("activity_end_time >= ?", time.Now()).And("state = ?", 1).Get(&av)

	if av.Id != 0 {

		x.Where("activity_id = ?", av.Id).Find(&av.CommodityList)
		for _, c := range av.CommodityList{
			var uc = UserCommodity{
				Id:          w.GetId(),
				UserId:      sr.SharedById,
				CommodityId: c.Id,
				CreatedAt:   time.Now(),
				UpdatedAt:   time.Now(),
			}
			x.Insert(&uc)
		}

		IntRrp := RangeRand(av.MinRandomRedPacket, av.MaxRandomRedPacket)
		floatRrp := rand.Float64()
		rrp := float64(IntRrp) + floatRrp

		var wr WalletRecords
		wr.Id = w.GetId()
		wr.GetRedPacketUserId = sr.SharerId
		wr.RedPacketAmount = rrp
		wr.CreatedAt = time.Now()
		wr.UpdatedAt = time.Now()
		x.Insert(&wr)

		var uv User
		uv.Wallet += rrp
		x.Where("id = ?", sr.SharerId).Update(&uv)

		return map[string]interface{}{"message": "成功","code":200}, nil
	}

	return map[string]interface{}{"message": "该活动已结束,十分抱歉","code":400}, nil
}

func (activity *Activity)EventPurchase(uId int64, aId int64)(map[string]interface{}, error){

	w := new(utils.Worker)

	var a Activity
	x.Id(aId).Get(&a)

	var uaList []*UserActivity
	x.Where("activity_id = ?", aId).And("user_id = ?", uId).Find(&uaList)
	if len(uaList) >= a.PurchaseCap{
		return map[string]interface{}{"message": "您已达到该活动的购买上限","code":400}, nil
	}

	var ua = UserActivity{
		Id:         w.GetId(),
		UserId:     uId,
		ActivityId: aId,
		CreatedAt:  time.Now(),
		UpdatedAt:  time.Now(),
	}
	x.Insert(&ua)

	return map[string]interface{}{"message": "成功","code":200}, nil
}

func (activity *Activity)IsActivity(aId int64, sId int64)(bool, error){

	var as ActivityStore
	x.Where("activity_id = ?", aId).And("store_id = ?", sId).Get(&as)
	if as.Id != 0{
		return true, nil
	}
	return false, nil
}

var lock sync.Mutex

func (activity *Activity)ParticipationActivity(aId int64, uId int64)(map[string]interface{}, error){

	w := new(utils.Worker)

	var a Activity
	x.Id(aId).Get(&a)

	lock.Lock()

	count, err := x.Where("activity_id = ?", aId).Count(new(ActivityParticipationRecords))
	if err != nil{

		lock.Unlock()

		return map[string]interface{}{"message": "失败","code":400}, nil
	}
	if int(count) >= a.Number {

		lock.Unlock()

		return map[string]interface{}{"message": "该活动已满员","code":400}, nil
	}

	var apr ActivityParticipationRecords
	x.Where("user_id = ?", uId).And("activity_id = ?", aId).Get(&apr)
	if apr.Id != 0{

		lock.Unlock()

		return map[string]interface{}{"message": "您已参与该活动，无需重复参与","code":400}, nil
	}else{
		apr.Id = w.GetId()
		apr.UserId = uId
		apr.ActivityId = aId
		apr.CreatedAt = time.Now()
		apr.UpdatedAt = time.Now()
		x.Insert(&apr)
	}

	lock.Unlock()

	return map[string]interface{}{"message": "成功","code":200}, nil
}

func (activity *Activity)QueryActivity()([]*Activity, error){

	var aList []*Activity
	x.Find(&aList)

	for _, a := range aList{
		x.Find(&a.StoreList)

		for _, s := range a.StoreList{
			var as ActivityStore
			x.Where("activity_id = ?", a.Id).And("store_id = ?", s.Id).Get(&as)
			if as.Id != 0{
				s.Participation = true
			}
		}
	}

	return aList, nil
}

func (activity *Activity)ExchangePrizes(uId int64, mmId int64, aId int64)(map[string]interface{}, error){

	w := new(utils.Worker)

	var u User
	x.Id(uId).Get(&u)

	var mm MedalManagement
	x.Id(mmId).Get(&mm)

	erCount, rErr := x.Where("user_id = ?", uId).And("medal_management_id = ?", mm.Id).Count(new(ExchangeRecords))
	if rErr != nil{
		return map[string]interface{}{"message": "失败","code":500}, nil
	}

	srCount, err := x.Where("sharer_id = ?", u.Id).And("activity_id = ?", aId).Count(new(ShareRecords))
	if err != nil{
		return map[string]interface{}{"message": "失败","code":500}, nil
	}

	if srCount - int64(mm.ExchangeRecommendation)*erCount < int64(mm.ExchangeRecommendation){
		return map[string]interface{}{"message": "未达到兑换的推荐单数","code":400}, nil
	}

	if erCount >= int64(mm.MaximumExchangeTimes){
		return map[string]interface{}{"message": "该奖品已达到最大兑换次数","code":400}, nil
	}

	var er = ExchangeRecords{
		Id:                  w.GetId(),
		UserId:              u.Id,
		MedalManagementId:   mm.Id,
		MedalManagementName: mm.Name,
		CreatedAt:           time.Now(),
		UpdatedAt:           time.Now(),
	}
	x.Insert(&er)

	mm.ConvertibleAmount -= 1
	x.Id(mm.Id).Update(&mm)

	return map[string]interface{}{"message": "成功","code":200}, nil
}


















